package org.example.mall.admin.configuration.auth.handler;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.Data;
import org.example.mall.admin.configuration.auth.CustomUser;
import org.example.mall.admin.configuration.auth.check.CheckAuthHandlerChain;
import org.example.mall.admin.configuration.auth.code.ScenesConst;
import org.example.mall.admin.model.entity.manage.AccountAuth;
import org.example.mall.admin.service.manage.AccountAuthService;
import org.example.mall.admin.service.manage.MenuService;
import org.example.mall.admin.util.SecurityUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import java.util.List;
import java.util.Map;

/**
 * 自定义登录抽象处理器
 *
 * @author hzq
 * @date 2021/12/10 13:45
 */
@Data
public abstract class AbstractAuthHandler implements AuthHandler {

    @Autowired
    protected AccountAuthService accountAuthService;
    @Autowired
    protected MenuService menuService;
    @Autowired
    protected CheckAuthHandlerChain checkAuthHandlerChain;

    @Override
    public UserDetails handler(String principal, String credentials, Map<String, String> parameters) {


        // 校验凭证
        checkCredentials(principal, credentials);

        // 查询用户信息
        AccountAuth auth = getNotNullAuth(principal);

        //检验用户
        checkAuth(auth);

        // 获取用户权限
        List<GrantedAuthority> userMenu = accountAuthorities(auth);

        // 已认证用户
        return new CustomUser(auth, userMenu);
    }

    /**
     * @return 权限列表
     */
    protected List<GrantedAuthority> accountAuthorities(AccountAuth auth) {
        return getMenuService().accountAuthorities(auth.getAccountId(), SecurityUtil.getClientId());
    }

    /**
     * 校验凭证
     *
     * @param principal   标识
     * @param credentials 凭证
     */
    protected void checkCredentials(String principal, String credentials) {
        // 检验
        getCheckAuthHandlerChain().check(ScenesConst.LOGIN, principal, credentials, getHandlerType());
    }

    /**
     * 获取用户信息
     *
     * @param principal 标识
     * @return 用户信息
     */
    protected AccountAuth getAuth(String principal) {

        LambdaQueryWrapper<AccountAuth> wrapper = Wrappers.<AccountAuth>lambdaQuery()
                .eq(AccountAuth::getAuthType, getHandlerType())
                .eq(AccountAuth::getPrincipal, principal);

        return getAccountAuthService().getOne(wrapper);
    }

    /**
     * 获取用户信息
     *
     * @param principal 标识
     * @return 用户信息
     */
    protected AccountAuth getNotNullAuth(String principal) {

        AccountAuth auth = getAuth(principal);

        if (auth == null) {
            throw new UsernameNotFoundException("用户不存在");
        }

        return auth;
    }

}
